﻿/* PCi DiRT 2 Bench Tool - Benchmark automation tool for DiRT 2
   Copyright © 2011, LEGRAND David
   Mail : david@pcinpact.com

   http://code.google.com/p/pci-gbs/

   This file is part of PCi DiRT 2 Bench Tool.

   PCi DiRT 2 Bench Tool is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   PCi DiRT 2 Bench Tool is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with PCi DiRT 2 Bench Tool.  If not, see <http://www.gnu.org/licenses/>.
 
   You're not allowed to use PC INpact name or logo without permission */

using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Xml;
using System.Threading.Tasks;

namespace PCi_DiRT_2_Bench_Tool
{

    public class DiRT2
    {

        public string ver;
        
        public string steam_dir;
        public string steam_app_code;

        public string app_dir; 
        public string app_process;
        public string app_args;
        public string app_out_folder;

        public string quality;
        public string dx9;
        public string res_w;
        public string res_h;
        public string fullscreen;
        public string aa;

        public string country;
        public string name;
        public string route;

        private string config = "hardware_settings_config.xml";

        public float benchmark(bool steam)
        {

            // On définit le processus qui permettra de lancer le bench
            Process benchmark = new Process();

            if (steam)
            {
                benchmark.StartInfo.FileName = steam_dir + @"\Steam.exe";
                benchmark.StartInfo.Arguments = "-applaunch " + steam_app_code + " " + app_args;
            }
            else
            {
                // On utilise la version du jeu pour déterminer l'exécutable à lancer
                if (ver == "d2") benchmark.StartInfo.FileName = app_dir + @"\dirt2.exe";
                else if (ver == "d3") benchmark.StartInfo.FileName = app_dir + @"\dirt3.exe";

                // Pour la version n'utilisant pas Steam, on change le répertoire de travail pour contenter SecuROM
                benchmark.StartInfo.Arguments = app_args;
                benchmark.StartInfo.WorkingDirectory = app_dir;
            }

            // On écrit le fichier de configuration
            write_config();

            // On supprime les fichiers de bench précédents
            if (Directory.Exists(app_out_folder) && Directory.GetFiles(app_out_folder).Length > 0)
            {
                foreach (string f in Directory.GetFiles(app_out_folder))
                {
                    System.IO.File.Delete(f);
                }
            }

            // On lance le test
            // On utilise une Task pour éviter de bloquer l'interface
            var tache = Task.Factory.StartNew(() =>
                {
                    benchmark.Start();
                    benchmark.WaitForExit();
                });
            tache.Wait();

            // Si l'on a demandé de passer par Steam
            // On détecte le lancement du processus et on attend sa fin manuellement
            if (steam)
            {
                // On récupère la liste des processus en cours
                Process[] prc = Process.GetProcessesByName(app_process);

                // On attend que le processus soit lancé
                while (prc.Length < 1)
                {
                    // Tant que ce n'est pas le cas, on attend une seconde
                    // Ensuite on récupère à nouveau la liste des processus en cours
                    // Et on recommance
                    Thread.Sleep(1000);
                    prc = Process.GetProcessesByName(app_process);
                }

                // On attend que le processus soit terminé avec la même méthode
                while (prc.Length > 0)
                {
                    Thread.Sleep(1000);
                    prc = Process.GetProcessesByName(app_process);
                }
            }
            
            // On renvoie la valeur finale
            return out_score(Directory.GetFiles(app_out_folder)[0]);
        }

        // Fonction de lecture du score
        private float out_score(string file_name)
        {
            // On ouvre le fichier XML
            XmlTextReader xtr = new XmlTextReader(file_name);

            // On déclare les variables utiles
            string fps = string.Empty;
            float out_fps;

            // On parcourt le fichier
            while (xtr.Read())
            {
                // Lorsque l'on trouve la bonne ligne
                if (xtr.Name == "average")
                {
                    // On trouve la bonne valeur
                    xtr.MoveToNextAttribute();
                    xtr.MoveToNextAttribute();

                    // On met en forme en remplaçant le . par une ,
                    fps = xtr.Value.Replace('.', ',');
                }
            }

            // On renvoie la variable sous forme de float
            float.TryParse(fps, out out_fps);

            // On ferme le fichier
            xtr.Close();

            // on renvoie la valeur finale
            return out_fps;
        }

        // La fonction qui permet de modifier le fichier XML de benchmark
        public void write_benchmark()
        {
            // On ouvre le fichier XML
            XmlDocument xd = new XmlDocument();
            
            // On gère les différentes versions
            if (ver == "d2") xd.LoadXml(PCi_GBS.Properties.Resources.d2_example_benchmark);
            else if (ver == "d3") xd.LoadXml(PCi_GBS.Properties.Resources.d3_example_benchmark);

            // On attribue les différents attributs aux différentes variables
            XmlAttribute x_country = xd.DocumentElement.ChildNodes[0].Attributes[0];
            XmlAttribute x_name = xd.DocumentElement.ChildNodes[0].Attributes[1];
            XmlAttribute x_route = xd.DocumentElement.ChildNodes[0].Attributes[2];
            
            // On leur passe les valeurs demandées
            x_country.Value = country;
            x_name.Value = name;
            x_route.Value = route;

            // On sauvegarde le fichier après avoir s'être assuré qu'il n'est pas en lecture seule
            File.SetAttributes(app_dir + "\\example_benchmark.xml", FileAttributes.Normal);
            xd.Save(app_dir + "\\example_benchmark.xml");

        }

        private void write_config()
        {
            // On ouvre le fichier XML
            XmlDocument xd = new XmlDocument();

            // On ouvre le fichier en fonction de la qualité demandée
            // On gère la version du jeu
            switch (quality)
            {
                case "tb":
                    if (ver == "d2") xd.LoadXml(PCi_GBS.Properties.Resources.d2_tres_bas);
                    else if (ver == "d3") xd.LoadXml(PCi_GBS.Properties.Resources.d3_tres_bas);
                    break;
                case "b":
                    if (ver == "d2") xd.LoadXml(PCi_GBS.Properties.Resources.d2_bas);
                    else if (ver == "d3") xd.LoadXml(PCi_GBS.Properties.Resources.d3_bas);
                    break;
                case "int":
                    if (ver == "d2") xd.LoadXml(PCi_GBS.Properties.Resources.d2_inter);
                    else if (ver == "d3") xd.LoadXml(PCi_GBS.Properties.Resources.d3_inter);
                    break;
                case "high":
                    if (ver == "d2") xd.LoadXml(PCi_GBS.Properties.Resources.d2_high);
                    else if (ver == "d3") xd.LoadXml(PCi_GBS.Properties.Resources.d3_high);
                    break;
                case "ultra":
                    if (ver == "d2") xd.LoadXml(PCi_GBS.Properties.Resources.d2_ultra);
                    else if (ver == "d3") xd.LoadXml(PCi_GBS.Properties.Resources.d3_ultra);
                    break;
                default:
                    if (ver == "d2") xd.LoadXml(PCi_GBS.Properties.Resources.d2_tres_bas);
                    else if (ver == "d3") xd.LoadXml(PCi_GBS.Properties.Resources.d3_tres_bas);
                    break;
            }

            // On attribue les différents attributs aux différentes variables
            XmlAttribute x_dx9 = xd.DocumentElement.ChildNodes[2].ChildNodes[0].Attributes[0];
            XmlAttribute x_res_w = xd.DocumentElement.ChildNodes[2].ChildNodes[1].Attributes[0];
            XmlAttribute x_res_h = xd.DocumentElement.ChildNodes[2].ChildNodes[1].Attributes[1];
            XmlAttribute x_full_screen = xd.DocumentElement.ChildNodes[2].ChildNodes[1].Attributes[3];
            XmlAttribute x_aa = xd.DocumentElement.ChildNodes[2].ChildNodes[1].Attributes[5];

            // On leur passe les valeurs demandées
            x_dx9.Value = dx9;
            x_res_w.Value = res_w;
            x_res_h.Value = res_h;
            x_full_screen.Value = fullscreen;
            x_aa.Value = aa;

            // On sauvegarde le fichier dans le répertoire de DiRT 2
            if (ver == "d2") xd.Save(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\My Games\\DiRT2\\hardwaresettings\\" + config);
            else if (ver == "d3") xd.Save(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\My Games\\DiRT3\\hardwaresettings\\" + config);

        }
    }
}
